import { Injectable, HttpException } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Repository } from 'typeorm'
import { RefundEntity } from './entities/refund.entity'
import { OrderEntity } from '../order/entities/order.entity'
import { DelRefundDto, ListRefundDto, RefundApplyDto, RefundOperateDto } from './dto/refund.dto'
import { getCurrentTime, handleTimeRange, sendWeComMsg } from '@/utils'
import { WalletLogService } from '../points/points.service'
import { OrderStatus, RefundStatus, walletType } from '@/mock'

@Injectable()
export class RefundService {
  constructor(
    @InjectRepository(RefundEntity)
    private readonly refundRepo: Repository<RefundEntity>,
    @InjectRepository(OrderEntity)
    private readonly orderRepo: Repository<OrderEntity>,
    private readonly walletLogService: WalletLogService,
  ) { }

  // 申请退款
  async applyRefund(data: RefundApplyDto, userId: number) {
    // 订单是否存在
    const order = await this.orderRepo.findOneBy({ id: data.order_id })
    if (!order) {
      throw new HttpException('订单不存在', 404)
    }

    // 验证订单状态（仅已支付订单可申请退款）
    if (order.status !== OrderStatus.PAID) {
      throw new HttpException('仅已支付的订单可申请退款', 400)
    }

    // 检查是否已存在待处理的退款申请
    const existingRefund = await this.refundRepo.findOneBy({
      order_id: data.order_id,
      status: RefundStatus.PENDING, // 待处理
    })
    if (existingRefund) {
      throw new HttpException('已提交退款申请，请等待商家处理', 400)
    }

    // 创建退款记录
    const refund = this.refundRepo.create({
      order_id: data.order_id,
      user_remark: data.user_remark,
      user_id: userId,
      status: RefundStatus.PENDING,
      apply_time: Math.floor(Date.now() / 1000)
    })

    // 更新订单状态为"退款中"
    await this.orderRepo.update({ id: data.order_id }, {
      status: OrderStatus.REFUNDING,
    })

    // 推送企微消息
    const nickname = `用户${userId}`
    const remarkText = data.user_remark ? `\n📝 退款原因：${data.user_remark}` : ''
    const currentTime = getCurrentTime()
    await sendWeComMsg(
      `${currentTime} ${nickname}申请退款\n` +
      `🧾 关联订单ID: ${data.order_id}\n` +
      `💰 退款金额：${order.total_fee}\n` +
      remarkText,
      'LiuXiaoLin'
    )
    return this.refundRepo.save(refund)
  }

  // 处理退款
  async handleRefund(data: RefundOperateDto, userId: number) {
    // 退款记录是否存在
    const refund = await this.refundRepo.findOneBy({ id: data.id })
    if (!refund) {
      throw new HttpException('退款记录不存在', 404)
    }

    // 验证退款状态（仅"待处理"的退款可操作）
    if (refund.status !== RefundStatus.PENDING) {
      throw new HttpException('该退款申请已处理，无需重复操作', 400)
    }

    const order = await this.orderRepo.findOneBy({ id: refund.order_id })
    if (!order) {
      throw new HttpException('关联的订单不存在', 404)
    }

    const currentTime = Math.floor(Date.now() / 1000)
    refund.status = data.status
    refund.merchant_remark = data.merchant_remark
    refund.operate_time = currentTime

    let orderStatus = 0
    // 同意退款 → 订单状态 => 已退款
    if (Number(data.status) === RefundStatus.AGREED) {
      orderStatus = OrderStatus.REFUNDED
      // 记录日志，退款
      await this.walletLogService.createTransaction(userId, walletType.REFUND, order.total_fee)
    } else {
      // 拒绝退款 → 订单状态 => 退款驳回
      orderStatus = OrderStatus.REFUND_REJECTED
    }
    await this.orderRepo.update(refund.order_id, { status: orderStatus })

    // 推送企微消息
    const handleCurrentTime = getCurrentTime()
    const refundResult = Number(data.status) === RefundStatus.AGREED ? '✅ 已同意' : '❌ 已拒绝'
    const amountDesc = Number(data.status) === RefundStatus.AGREED ? `💰 退款金额：${order.total_fee}` : ''
    const remarkText = data.merchant_remark ? `\n📝 商家说明：${data.merchant_remark}` : ''
    const balanceDesc = Number(data.status) === RefundStatus.AGREED ? `💳 退款将原路退回，预计1-3个工作日到账，请注意查收` : ''

    await sendWeComMsg(
      `${handleCurrentTime} 您的退款申请已处理\n` +
      `🧾 关联订单ID: ${refund.order_id}\n` +
      `处理结果：${refundResult}\n` +
      `${amountDesc}\n` +
      `${remarkText}\n` +
      `${balanceDesc}\n` +
      `感谢您的理解与支持，祝您用餐愉快！`,
      'BeiShangKaoTuDou'
    )

    return this.refundRepo.save(refund)
  }

  // 退款列表
  async refundList(data: ListRefundDto) {
    const qb = await this.refundRepo.createQueryBuilder('refund')
    qb.orderBy('refund.apply_time', 'DESC')
    qb.andWhere('refund.is_del = :is_del', { is_del: 0 })
    // qb.andWhere('refund.user_id = :user_id', { user_id: data.user_id })

    // 允许查询的字段白名单
    const validFields = ['order_id', 'status', 'apply_time', 'operate_time']

    const { page = 1, pageSize = 10, start, end, operateStart, operateEnd, ...params } = data
    Object.entries(params).forEach(([key, value]) => {
      if (!['', undefined, null].includes(value as any) && validFields.includes(key)) {
        qb.andWhere(`refund.${key} = :${key}`, { [key]: key === 'status' ? Number(value) : value })
      }
    })

    handleTimeRange(qb, 'refund', 'apply_time', 'start', 'end', data)
    handleTimeRange(qb, 'refund', 'operate_time', 'operateStart', 'operateEnd', data)
    const pageNum = Math.max(1, Number(page) || 1)
    const pageSizeNum = Math.min(100, Math.max(1, Number(pageSize) || 10))
    const total = await qb.getCount()
    const temp = (await qb.skip((pageNum - 1) * pageSizeNum).take(pageSizeNum).getMany()).map(({ is_del, user_id, ...rest }) => rest)

    return {
      entries: temp,
      total
    }
  }

  // 退款删除
  async deleteRefund(data: DelRefundDto) {
    // 退款记录是否存在
    const refund = await this.refundRepo.findOneBy({ id: data.id })
    if (!refund) {
      throw new HttpException('退款记录不存在', 404)
    }

    // 验证退款状态（仅"待处理"的退款可操作）
    if (refund.status !== RefundStatus.PENDING) {
      throw new HttpException('该退款申请已处理，无需重复操作', 400)
    }

    // 更新退款记录为已删除
    await this.refundRepo.update(refund.id, {
      is_del: 1,
      operate_time: Math.floor(Date.now() / 1000)
    })

    return {
      message: '退款记录已删除',
    }
  }
}
